import 'dart:io';

import 'package:dio/io.dart';
import 'package:dio/dio.dart';
import 'package:todo_app/components/Overlay/main.dart';
import 'package:todo_app/utils/ExtHelper.dart';
import '../config/config.dart';
import 'AppNavigator.dart';
import 'SharedPreferencesUtil.dart';

class ApiService {
  static var dio = Dio();
  static var ACCESS_TOKEN = 'ACCESS_TOKEN';
  static var baseServer = AppConfig.api;
  static Map<String, dynamic> serverErrorData = {
    "data": null,
    "code": 500,
    "message": "网络错误"
  };

  static init() {
      (dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate = (client){
        client.badCertificateCallback=(cert, host, port){
          return true;
        };
      };
  }


  static Future handleError(Response<dynamic> response, String path) async {
    if(response.statusCode != 200) {
      showOverlayToast('服务端错误 code=${response.statusCode}');
    } else if(response.statusCode == 200 && response.data['code'] != 200) {
      if(response.data['code'] == 401) {
       AppNavigator.toLoginPage();
      }
    }
    print(path);
    print(response);
  }

  static Future<Response<dynamic>> post(String path, dynamic data, [Map<String, dynamic>? headers, Map<String, dynamic>? queryParameters]) async {
    var _headers = getHeaders();
    if(headers != null) _headers.addAll(headers);
    try {
      var response = await dio.post(
        path.startsWith('http') ? path : baseServer + path,
        data: data is Map<String, dynamic> ? data.noNull : data,
        queryParameters: queryParameters,
        options: Options(
          contentType: _headers['Content-Type'] ?? Headers.jsonContentType,
          headers: _headers
        )
      );
      handleError(response, path);
      return response;
    } on DioError catch (error) { 
      return error.response ?? Response(statusMessage: error.message, statusCode: 500, data: serverErrorData, requestOptions: RequestOptions(path: path, data: data, headers: headers));
    } catch(e) {
      return Response(data: null, requestOptions: RequestOptions(path: path, data: data, headers: headers));
    }
  }


  static Future<Response<dynamic>> put(String path, dynamic data, Map<String, dynamic>? headers) async {
    var _headers = getHeaders();
    if(headers != null) _headers.addAll(headers);
    try {
      var response = await dio.put(
        baseServer + path,
        data: data is Map<String, dynamic> ? data.noNull : data,
        options: Options(
          contentType: Headers.jsonContentType,
          headers: _headers
        )
      );
      handleError(response, path);
      return response;
    } on DioError catch (error) { 
      return Response(statusMessage: error.message, statusCode: 500, data: serverErrorData, requestOptions: RequestOptions(path: path, data: data, headers: headers));
    } catch(e) {
      return Response(data: null, requestOptions: RequestOptions(path: path, data: data, headers: headers));
    }
  }

  static Future<Response<dynamic>> get(String path, Map<String, dynamic>? queryParameters, Map<String, dynamic>? headers) async {
    var _headers = getHeaders();
    print(path);
    if(headers != null) _headers.addAll(headers);
    try {
      var response = await dio.get(
        baseServer + path,
        queryParameters: queryParameters?.noNull,
        options: Options(
          contentType: Headers.jsonContentType,
          headers: _headers
        )
      );
      handleError(response, path);
      return response;
    } on DioError catch (error) { 
      return Response(statusMessage: error.message, statusCode: 500, data: serverErrorData, requestOptions: RequestOptions(path: path, data: null, headers: headers));
    } catch(e) {
      return Response(data: null, requestOptions: RequestOptions(path: path, data: serverErrorData, headers: headers));
    }
  }

  static Future<Response<dynamic>> delete(String path, Map<String, dynamic>? queryParameters, Map<String, dynamic>? headers) async {
    var _headers = getHeaders();
    if(headers != null) _headers.addAll(headers);
    try {
      var response = await dio.delete(
        baseServer + path,
        queryParameters: queryParameters?.noNull,
        options: Options(
          contentType: Headers.jsonContentType,
          headers: _headers
        )
      );
      handleError(response, path);
      return response;
    } on DioError catch (error) { 
      return Response(statusMessage: error.message, statusCode: 500, data: serverErrorData, requestOptions: RequestOptions(path: path, data: null, headers: headers));
    } catch(e) {
      return Response(data: null, requestOptions: RequestOptions(path: path, data: serverErrorData, headers: headers));
    }
  }


  static Future<Response<dynamic>> upload(String path, String name, File file, Map<String, dynamic>? headers) async {
    var _headers = getHeaders();
    if(headers != null) _headers.addAll(headers);
    var data = FormData.fromMap(<String ,dynamic>{
      name: await MultipartFile.fromFile(file.path)
    });
    try {
      var response = await dio.post(
        baseServer + path,
        data: data,
        options: Options(
          contentType: Headers.multipartFormDataContentType,
          headers: _headers
        )
      );
      handleError(response, path);
      return response;
    } on DioError catch (error) { 
      return Response(statusMessage: error.message, statusCode: 500, data: serverErrorData, requestOptions: RequestOptions(path: path, data: data, headers: headers));
    } catch(e) {
      return Response(data: null, requestOptions: RequestOptions(path: path, data: data, headers: headers));
    }
  }

  static Map<String, dynamic> getHeaders() {
    String token = SharedPreferenceUtil.getString(ACCESS_TOKEN);
    return {
      "Content-Type": "application/json",
      "Authorization": "Bearer $token"
    };
  }
}